package com.tools.common.container;

import com.tools.common.container.r.OnlyReadHashMap;
import com.tools.common.container.r.OnlyReadLinkedMap;
import com.tools.common.container.r.OnlyReadMap;
import com.tools.common.container.r.OnlyReadTreeMap;
import com.tools.common.exception.NotFoundDataException;
import com.tools.common.object.BasicEnum;
import com.tools.common.object.C;
import com.tools.common.object.Note;
import com.tools.common.object.ObjKit;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentSkipListMap;

/**
 * Map 集合实现类枚举
 * 用于更方便灵活地构建
 * Map 集合
 * */
@Note("Map 集合实现类枚举，用于更方便灵活地构建 Map 集合")
public enum MapEnum {

    HASH(HashMap.class, "java.util.HashMap"),

    LINKED(LinkedHashMap.class, "java.util.LinkedHashMap"),

    CONCURRENT(ConcurrentHashMap.class, "java.util.concurrent.ConcurrentHashMap"),

    TREE(TreeMap.class, "java.util.TreeMap"),

    SKIP_LIST(ConcurrentSkipListMap.class, "java.util.concurrent.ConcurrentSkipListMap");

    @Note("Map 集合实现类的全限定类名")
    private final Class<?> implClass;

    @Note("Map 集合实现类的字节码")
    private final String implClassname;

    @Note("HashMap 容器最大的容量，为 int 类型的最大值 2^31")
    public static final int MAX_SIZE = 1 << 30;

    MapEnum(Class<?> implClass, String implClassname) {
        this.implClass = implClass;
        this.implClassname = implClassname;
    }

    public Class<?> getImplClass() {
        return implClass;
    }

    public String getImplClassname() {
        return implClassname;
    }

    @Override
    public String toString() {
        return implClassname;
    }

    @Note("按照 HashMap 集合的扩容算法，计算出最合理的初始化容量，尽可能地减少扩容次数")
    public static int calcInitSize(int size) {
        if(size <= 0) return 0;
        int newSize = (int) (size / 0.75f + 1.0f);
        return Math.min(newSize, MAX_SIZE);
    }


    @Note("按照 HashMap 集合的扩容算法，使用指定的加载因子计算出最合理的初始化容量，尽可能地减少扩容次数")
    public static int calcInitSize(int size, float loadFactor) {
        if (loadFactor <= 0 || Float.isNaN(loadFactor)) {
            throw new IllegalArgumentException("非法的加载因子: " + loadFactor);
        }
        if(size <= 0) return 0;
        int newSize = (int) (size / loadFactor + 1.0f);
        return Math.min(newSize, MAX_SIZE);
    }


    @Note("获取入参 Map 集合的容量，按照 HashMap 集合的扩容算法，计算出最合理的初始化容量，尽可能地减少扩容次数")
    public static int calcInitSize(Map map) {
        if(map == null) return 0;
        int size = map.size();
        if(size == 0) return 0;
        int newSize = (int) (size / 0.75f + 1.0f);
        return Math.min(newSize, MAX_SIZE);
    }


    @Note("获取入参自定义键值对集合的容量，按照 HashMap 集合的扩容算法，计算出最合理的初始化容量，尽可能地减少扩容次数")
    public static int calcInitSize(OwnPairs pairs) {
        if(pairs == null) return 0;
        int size = pairs.size();
        if(size == 0) return 0;
        int newSize = (int) (size / 0.75f + 1.0f);
        return Math.min(newSize, MAX_SIZE);
    }

    /* *******************************************************************************************
     *
     *          获取枚举实例
     *
     * *******************************************************************************************
     * */

    /**
     * @param implClass Map 实现类的字节码
     * @return 安全地根据 implClass 字节码获取映射的 MapEnum 实例，获取不到不会抛异常
     * */
    @Note("安全地根据 implClass 字节码获取映射的 MapEnum 实例，获取不到不会抛异常")
    public static MapEnum getEnumSafe(Class<?> implClass) {
        if(HASH.implClass.equals(implClass)) {
            return HASH;
        }
        if(CONCURRENT.implClass.equals(implClass)) {
            return CONCURRENT;
        }
        if(LINKED.implClass.equals(implClass)) {
            return LINKED;
        }
        if(TREE.implClass.equals(implClass)) {
            return TREE;
        }
        if(SKIP_LIST.implClass.equals(implClass)) {
            return SKIP_LIST;
        }
        return null;
    }

    /**
     * @param implClass Map 实现类的字节码
     * @return 根据 implClass 字节码获取映射的 MapEnum 实例，获取不到会抛异常
     * */
    @Note("根据 implClass 字节码获取映射的 MapEnum 实例，获取不到会抛异常")
    public static MapEnum getEnum(Class<?> implClass) {
        MapEnum mapEnum = getEnumSafe(implClass);
        if(mapEnum == null) throw new IllegalArgumentException("不知道【" + implClass + "】对应的是什么枚举实例");
        return mapEnum;
    }

    /**
     * @param implClassname Map 实现类的全路径
     * @return 根据 implClassname 全路径获取映射的 MapEnum 实例，获取不到不会抛异常
     * */
    @Note("安全地根据 implClassname 全路径获取映射的 MapEnum 实例，获取不到不会抛异常")
    public static MapEnum getEnumSafe(String implClassname) {
        if(HASH.implClassname.equalsIgnoreCase(implClassname)) {
            return HASH;
        }
        if(LINKED.implClassname.equalsIgnoreCase(implClassname)) {
            return LINKED;
        }
        if(TREE.implClassname.equalsIgnoreCase(implClassname)) {
            return TREE;
        }
        if(CONCURRENT.implClassname.equalsIgnoreCase(implClassname)) {
            return CONCURRENT;
        }
        if(SKIP_LIST.implClassname.equalsIgnoreCase(implClassname)) {
            return SKIP_LIST;
        }
        return null;
    }


    /**
     * @param implClassname Map 实现类的全路径
     * @return 根据 implClassname 全路径获取映射的 MapEnum 实例，获取不到会抛异常
     * */
    @Note("根据 implClassname 全路径获取映射的 MapEnum 实例，获取不到会抛异常")
    public static MapEnum getEnum(String implClassname) {
        MapEnum mapEnum = getEnumSafe(implClassname);
        if(mapEnum == null) throw new IllegalArgumentException("不知道【" + implClassname + "】对应的是什么枚举实例");
        return mapEnum;
    }

    /* *******************************************************************************************
     *
     *          直接构造 Map 集合
     *
     * *******************************************************************************************
     * */


    /**
     * @return 根据枚举值构建不同实现类实现的 Map 集合
     * */
    @Note("根据枚举值构建不同实现类实现的 Map 集合")
    public <K, V> Map<K, V> newMap() {
        switch (this) {
            case HASH: return new HashMap<>();
            case LINKED: return new LinkedHashMap<>();
            case CONCURRENT: return new ConcurrentHashMap<>();
            case TREE: return new TreeMap<>();
            case SKIP_LIST: return new ConcurrentSkipListMap<>();
        }
        throw new NotFoundDataException("没找到枚举实例: " + this.toString());
    }


    /**
     * @param initSize 初始化 HashMap / LinkedHashMap / ConcurrentHashMap 时，指定容器的大小
     * @return 根据枚举值，用不同的实现类实现 Map 集合，如果是可以指定容量的则指定其初始化大小为 initSize
     * */
    @Note("根据枚举值，用不同的实现类实现 Map 集合，如果是可以指定容量的则指定其初始化大小为 initSize")
    public <K, V> Map<K, V> newMap(int initSize) {
        switch (this) {
            case HASH: return (initSize <= 0) ? new HashMap<>() : new HashMap<>(calcInitSize(initSize));
            case LINKED: return (initSize <= 0) ? new LinkedHashMap<>() : new LinkedHashMap<>(calcInitSize(initSize));
            case CONCURRENT: return (initSize <= 0) ? new ConcurrentHashMap<>() : new ConcurrentHashMap<>(calcInitSize(initSize));
            case TREE: return new TreeMap<>();
            case SKIP_LIST: return new ConcurrentSkipListMap<>();
        }
        throw new NotFoundDataException("没找到枚举实例: " + this.toString());
    }



    /**
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据枚举值，用不同的实现类实现 Map 集合，如果实现类是 TreeMap 则默认指定入参的 Comparator 排序比较器
     * */
    @Note("根据枚举值，用不同的实现类实现 Map 集合，如果实现类是 TreeMap 则默认指定入参的 Comparator 排序比较器")
    public <K, V> Map<K, V> newMap(Comparator<? super K> c) {
        switch (this) {
            case HASH: return new HashMap<>();
            case LINKED: return new LinkedHashMap<>();
            case CONCURRENT: return new ConcurrentHashMap<>();
            case TREE: return new TreeMap<>(c);
            case SKIP_LIST: return new ConcurrentSkipListMap<>(c);
        }
        throw new NotFoundDataException("没找到枚举实例: " + this.toString());
    }


    /**
     * @param initSize 初始化 HashMap / LinkedHashMap / ConcurrentHashMap 时，指定容器的大小
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据枚举值，用不同的实现类实现 Map 集合，根据不同的实现类可选择不同的入参增强初始化操作
     * */
    @Note("根据枚举值，用不同的实现类实现 Map 集合，根据不同的实现类可选择不同的入参增强初始化操作")
    public <K, V> Map<K, V> newMap(int initSize, Comparator<? super K> c) {
        switch (this) {
            case HASH: return (initSize <= 0) ? new HashMap<>() : new HashMap<>(calcInitSize(initSize));
            case LINKED: return (initSize <= 0) ? new LinkedHashMap<>() : new LinkedHashMap<>(calcInitSize(initSize));
            case CONCURRENT: return (initSize <= 0) ? new ConcurrentHashMap<>() : new ConcurrentHashMap<>(calcInitSize(initSize));
            case TREE: return new TreeMap<>(c);
            case SKIP_LIST: return new ConcurrentSkipListMap<>(c);
        }
        throw new NotFoundDataException("没找到枚举实例: " + this.toString());
    }


    /**
     * @param map 源 Map 集合
     * @return 根据枚举值用不同的实现类构建一个新的 Map 集合，然后把源 Map 里的数据拷贝到新 Map 集合里
     * */
    @Note("根据枚举值用不同的实现类构建一个新的 Map 集合，然后把源 Map 里的数据拷贝到新 Map 集合里")
    public <K, V> Map<K, V> newMap(Map<? extends K, ? extends V> map) {
        switch (this) {
            case HASH: return ObjKit.toHashMap(map);
            case LINKED: return ObjKit.toLinkedHashMap(map);
            case CONCURRENT: return ObjKit.toConcurrentHashMap(map);
            case TREE: return ObjKit.toTreeMap(map);
            case SKIP_LIST: return ObjKit.toConcurrentSkipListMap(map);
        }
        throw new NotFoundDataException("没找到枚举实例: " + this.toString());
    }


    /**
     * @param map 源 Map 集合
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据枚举值用不同的实现类构建一个新的 Map 集合，然后把源 Map 里的数据拷贝到新 Map 集合里
     * 如果实现类是 TreeMap 则指定入参的排序比较器
     * */
    @Note("根据枚举值用不同的实现类构建一个新的 Map 集合，然后把源 Map 里的数据拷贝到新 Map 集合里，" +
            "如果实现类是 TreeMap 则指定入参的排序比较器")
    public <K, V> Map<K, V> newMap(Map<? extends K, ? extends V> map, Comparator<? super K> c) {
        switch (this) {
            case HASH: return ObjKit.toHashMap(map);
            case LINKED: return ObjKit.toLinkedHashMap(map);
            case CONCURRENT: return ObjKit.toConcurrentHashMap(map);
            case TREE: return ObjKit.toTreeMap(map, c);
            case SKIP_LIST: return ObjKit.toConcurrentSkipListMap(map, c);
        }
        throw new NotFoundDataException("没找到枚举实例: " + this.toString());
    }


    /**
     * @param pair 源键值对容器集合
     * @return 根据枚举值用不同的实现类构建一个新的 Map 集合，然后把源键值对容器里的数据拷贝到新 Map 集合里
     * */
    @Note("根据枚举值用不同的实现类构建一个新的 Map 集合，然后把源键值对容器里的数据拷贝到新 Map 集合里")
    public <K, V> Map<K, V> newMap(OwnPairs<? extends K, ? extends V> pair) {
        switch (this) {
            case HASH: return ObjKit.toHashMap(pair);
            case LINKED: return ObjKit.toLinkedHashMap(pair);
            case TREE: return ObjKit.toTreeMap(pair);
            case CONCURRENT: return ObjKit.toConcurrentHashMap(pair);
            case SKIP_LIST: return ObjKit.toConcurrentSkipListMap(pair);
        }
        throw new NotFoundDataException("没找到枚举实例: " + this.toString());
    }


    /**
     * @param pair 源键值对容器集合
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据枚举值用不同的实现类构建一个新的 Map 集合，然后把源键值对容器里的数据拷贝到新 Map 集合里
     * 如果实现类是 TreeMap 则指定入参的排序比较器
     * */
    @Note("根据枚举值用不同的实现类构建一个新的 Map 集合，然后把源键值对容器里的数据拷贝到新 Map 集合里，" +
            "如果实现类是 TreeMap 则指定入参的排序比较器")
    public <K, V> Map<K, V> newMap(OwnPairs<? extends K, ? extends V> pair, Comparator<? super K> c) {
        switch (this) {
            case HASH: return ObjKit.toHashMap(pair);
            case LINKED: return ObjKit.toLinkedHashMap(pair);
            case TREE: return ObjKit.toTreeMap(pair, c);
            case CONCURRENT: return ObjKit.toConcurrentHashMap(pair);
            case SKIP_LIST: return ObjKit.toConcurrentSkipListMap(pair, c);
        }
        throw new NotFoundDataException("没找到枚举实例: " + this.toString());
    }


    /* *******************************************************************************************
     *
     *          静态 “字节码” 方式构建 Map 集合
     *
     * *******************************************************************************************
     * */

    /**
     * @param implClass Map 集合实现类的字节码
     * @return 使用 Map 集合指定的实现类来构建出一个 Map 集合
     * */
    @Note("使用 Map 集合指定的实现类来构建出一个 Map 集合")
    public static <K, V> Map<K, V> newMap(Class<?> implClass) {
        return private_getEnumIfNotExistsThrowException(implClass).newMap();
    }


    /**
     * @param implClass Map 集合实现类的字节码
     * @param initSize 初始化 HashMap / LinkedHashMap / ConcurrentHashMap 时，指定容器的大小
     * @return 根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，如果是可以指定容量的则指定其初始化大小为 initSize
     * */
    @Note("根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，如果是可以指定容量的则指定其初始化大小为 initSize")
    public static <K, V> Map<K, V> newMap(Class<?> implClass, int initSize) {
        return private_getEnumIfNotExistsThrowException(implClass).newMap(initSize);
    }


    /**
     * @param implClass Map 集合实现类的字节码
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，
     * 如果实现类是 TreeMap 则默认指定入参的 Comparator 排序比较器
     * */
    @Note("根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，" +
            "如果实现类是 TreeMap 则默认指定入参的 Comparator 排序比较器")
    public static <K, V> Map<K, V> newMap(Class<?> implClass, Comparator<? super K> c) {
        return private_getEnumIfNotExistsThrowException(implClass).newMap(c);
    }


    /**
     * @param implClass Map 集合实现类的字节码
     * @param initSize 初始化 HashMap / LinkedHashMap / ConcurrentHashMap 时，指定容器的大小
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，
     * 根据不同的实现类可选择不同的入参增强初始化操作
     * */
    @Note("根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，" +
            "根据不同的实现类可选择不同的入参增强初始化操作")
    public static <K, V> Map<K, V> newMap(Class<?> implClass, int initSize, Comparator<? super K> c) {
        return private_getEnumIfNotExistsThrowException(implClass).newMap(initSize, c);
    }



    /**
     * @param implClass Map 集合实现类的字节码
     * @param map 源 Map 集合
     * @return 根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，接着把源 Map 集合里的数据拷贝到内部
     * */
    @Note("根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，接着把源 Map 集合里的数据拷贝到内部")
    public static <K, V> Map<K, V> newMap(Class<?> implClass, Map<? extends K, ? extends V> map) {
        return private_getEnumIfNotExistsThrowException(implClass).newMap(map);
    }

    /**
     * @param implClass Map 集合实现类的字节码
     * @param map 源 Map 集合
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，接着把源 Map 集合里的数据拷贝到内部
     * 如果实现类是 TreeMap 则指定该比较器
     * */
    @Note("根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，接着把源 Map 集合里的数据拷贝到内部，" +
            "如果实现类是 TreeMap 则指定该比较器")
    public static <K, V> Map<K, V> newMap(Class<?> implClass, Comparator<? super K> c, Map<? extends K, ? extends V> map) {
        return private_getEnumIfNotExistsThrowException(implClass).newMap(map, c);
    }

    /**
     * @param implClass Map 集合实现类的字节码
     * @param pair 源键值对容器
     * @return 根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，然后把源键值对容器里的数据拷贝到该 Map 集合里
     * */
    @Note("根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，然后把源键值对容器里的数据拷贝到该 Map 集合里")
    public static <K, V> Map<K, V> newMap(Class<?> implClass, OwnPairs<? extends K, ? extends V> pair) {
        return private_getEnumIfNotExistsThrowException(implClass).newMap(pair);
    }


    /**
     * @param implClass Map 集合实现类的字节码
     * @param pair 源键值对容器
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，然后把源键值对容器里的数据拷贝到该 Map 集合里
     * 其中 TreeMap 会指定入参的排序比较器
     * */
    @Note("根据实现类的字节码得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，然后把源键值对容器里的数据拷贝到该 Map 集合里，" +
            "其中 TreeMap 会指定入参的排序比较器")
    public static <K,V> Map<K,V> newMap(Class<?> implClass, Comparator<? super K> c, OwnPairs<? extends K, ? extends V> pair) {
        return private_getEnumIfNotExistsThrowException(implClass).newMap(pair, c);
    }

    /* *******************************************************************************************
     *
     *          静态 “全路径” 方式构建 Map 集合
     *
     * *******************************************************************************************
     * */

    /**
     * @param classname Map 集合实现类的全限定路径
     * @return 使用 Map 集合指定的实现类来构建出一个 Map 集合
     * */
    @Note("使用 Map 集合指定的实现类来构建出一个 Map 集合")
    public static <K,V> Map<K,V> newMap(String classname) {
        return private_getEnumIfNotExistsThrowException(classname).newMap();
    }


    /**
     * @param classname Map 集合实现类的全限定路径
     * @param initSize 初始化 HashMap / LinkedHashMap / ConcurrentHashMap 时，指定容器的大小
     * @return 根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，如果是可以指定容量的则指定其初始化大小为 initSize
     * */
    @Note("根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，如果是可以指定容量的则指定其初始化大小为 initSize")
    public static <K,V> Map<K,V> newMap(String classname, int initSize) {
        return private_getEnumIfNotExistsThrowException(classname).newMap(initSize);
    }


    /**
     * @param classname Map 集合实现类的全限定路径
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，
     * 如果实现类是 TreeMap 则默认指定入参的 Comparator 排序比较器
     * */
    @Note("根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，" +
            "如果实现类是 TreeMap 则默认指定入参的 Comparator 排序比较器")
    public static <K,V> Map<K,V> newMap(String classname, Comparator<? super K> c) {
        return private_getEnumIfNotExistsThrowException(classname).newMap(c);
    }


    /**
     * @param classname Map 集合实现类的全限定路径
     * @param initSize 初始化 HashMap / LinkedHashMap / ConcurrentHashMap 时，指定容器的大小
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，
     * 根据不同的实现类可选择不同的入参增强初始化操作
     * */
    @Note("根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，" +
            "根据不同的实现类可选择不同的入参增强初始化操作")
    public static <K,V> Map<K,V> newMap(String classname, int initSize, Comparator<? super K> c) {
        return private_getEnumIfNotExistsThrowException(classname).newMap(initSize, c);
    }



    /**
     * @param classname Map 集合实现类的全限定路径
     * @param map 源 Map 集合
     * @return 根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，接着把源 Map 集合里的数据拷贝到内部
     * */
    @Note("根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，接着把源 Map 集合里的数据拷贝到内部")
    public static <K,V> Map<K,V> newMap(String classname, Map<? extends K, ? extends V> map) {
        return private_getEnumIfNotExistsThrowException(classname).newMap(map);
    }

    /**
     * @param classname Map 集合实现类的全限定路径
     * @param map 源 Map 集合
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，接着把源 Map 集合里的数据拷贝到内部
     * 如果实现类是 TreeMap 则指定该比较器
     * */
    @Note("根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，接着把源 Map 集合里的数据拷贝到内部，" +
            "如果实现类是 TreeMap 则指定该比较器")
    public static <K,V> Map<K,V> newMap(String classname, Comparator<? super K> c, Map<? extends K, ? extends V> map) {
        return private_getEnumIfNotExistsThrowException(classname).newMap(map, c);
    }

    /**
     * @param classname Map 集合实现类的全限定路径
     * @param pair 源键值对容器
     * @return 根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，然后把源键值对容器里的数据拷贝到该 Map 集合里
     * */
    @Note("根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，然后把源键值对容器里的数据拷贝到该 Map 集合里")
    public static <K,V> Map<K,V> newMap(String classname, OwnPairs<? extends K, ? extends V> pair) {
        return private_getEnumIfNotExistsThrowException(classname).newMap(pair);
    }


    /**
     * @param classname Map 集合实现类的全限定路径
     * @param pair 源键值对容器
     * @param c 排序比较器，如果实现类是 TreeMap 则指定该比较器
     * @return 根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，然后把源键值对容器里的数据拷贝到该 Map 集合里
     * 其中 TreeMap 会指定入参的排序比较器
     * */
    @Note("根据实现类的全路径得到映射的枚举值，然后构造出对应实现类实现的 Map 集合，然后把源键值对容器里的数据拷贝到该 Map 集合里，" +
            "其中 TreeMap 会指定入参的排序比较器")
    public static <K,V> Map<K,V> newMap(String classname, Comparator<? super K> c, OwnPairs<? extends K, ? extends V> pair) {
        return private_getEnumIfNotExistsThrowException(classname).newMap(pair, c);
    }


    /* *******************************************************************************************
     *
     *          反射构建 Map 集合
     *
     * *******************************************************************************************
     * */

    /**
     * @param mapType Map 集合的类型包装对象
     * @param initSize 构建 Map 集合的初始化容量
     * @return 根据类型包装对象构建出指定初始化容量的 Map 集合
     * */
    @Note("根据类型包装对象构建出指定初始化容量的 Map 集合")
    public static Map buildMap(C<?> mapType, int initSize) {
        return private_buildMapByC(mapType, initSize);
    }

    /**
     * @param mapType Map 集合的类型包装对象
     * @param map 装载数据的 Map 集合
     * @return 根据类型包装对象构建出 Map 集合，然后把 Map 的数据按要求拷贝进去
     * */
    @Note("根据类型包装对象构建出 Map 集合，然后把 Map 的数据按要求拷贝进去")
    public static Map buildMap(C<?> mapType, Map map) {
        Map result = private_buildMapByC(mapType, map.size());
        if(mapType.hasGenericType()) {
            C<?> keyType = mapType.generic(0);
            C<?> valueType = mapType.generic(1);
            Class<?> mainType = mapType.getMainType();
            for(Object o : map.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                Object realKey = private_handleKeyByMap(e.getKey(), keyType, mainType);
                Object realValue = ObjKit.toRealValue(e.getValue(), valueType);
                result.put(realKey, realValue);
            }
            return result;
        }
        result.putAll(map);
        return result;
    }

    /**
     * @param mapType Map 集合的类型包装对象
     * @param pairs 装载数据的自定义键值对容器
     * @return 根据类型包装对象构建出 Map 集合，然后把自定义键值对容器里的数据按要求拷贝进去
     * */
    @Note("根据类型包装对象构建出 Map 集合，然后把自定义键值对容器里的数据按要求拷贝进去")
    public static Map buildMap(C<?> mapType, OwnPairs pairs) {
        Map result = private_buildMapByC(mapType, pairs.size());
        if(mapType.hasGenericType()) {
            for (Object o : pairs.entrySet()) {
                Map.Entry e = (Map.Entry) o;
                result.put(e.getKey(), e.getValue());
            }
            return result;
        }
        Class<?> mainType = mapType.getMainType();
        C<?> valueType = mapType.generic(1);
        C<?> keyType = mapType.generic(0);
        for(Object o : pairs.keySet()) {
            Map.Entry e = (Map.Entry) o;
            Object realKey = private_handleKeyByMap(e.getKey(), keyType, mainType);
            Object realValue = ObjKit.toRealValue(e.getValue(), valueType);
            result.put(realKey, realValue);
        }
        return result;
    }

    /* *******************************************************************************************
     *
     *          反射构建自定义键值对集合
     *
     * *******************************************************************************************
     * */

    /**
     * @param pairType 自定义键值对容器的类型包装对象
     * @param initSize 构建自定义键值对容器的初始化容量
     * @return 根据类型包装对象构建出指定初始化容量的自定义键值对容器
     * */
    @Note("根据类型包装对象构建出指定初始化容量的自定义键值对容器")
    public static OwnPairs buildPair(C<?> pairType, int initSize) {
        return private_buildPairByC(pairType, Math.max(initSize, 0));
    }

    /**
     * @param pairType 自定义键值对容器的类型包装对象
     * @param map 装载数据的 Map 集合
     * @return 根据类型包装对象构建出自定义键值对容器，然后把 Map 集合里的数据按要求拷贝进去
     * */
    @Note("根据类型包装对象构建出自定义键值对容器，然后把 Map 集合里的数据按要求拷贝进去")
    public static OwnPairs buildPair(C<?> pairType, Map map) {
        OwnPairs result = private_buildPairByC(pairType, map.size());
        if(pairType.hasGenericType()) {
            C<?> keyType = pairType.generic(0);
            C<?> valueType = pairType.generic(1);
            for(Object o : map.entrySet()) {
                private_pairsPutOperation(o, result, keyType, valueType);
            }
            return result;
        }
        result.putAll(map);
        return result;
    }


    /**
     * @param pairType 自定义键值对容器的类型包装对象
     * @param pairs 装载数据的自定义键值对容器
     * @return 根据类型包装对象构建出自定义键值对容器，然后把有数据的目标自定义键值对容器里的数据按要求拷贝进去
     * */
    @Note("根据类型包装对象构建出自定义键值对容器，然后把有数据的目标自定义键值对容器里的数据按要求拷贝进去")
    public static OwnPairs buildPair(C<?> pairType, OwnPairs pairs) {
        OwnPairs result = private_buildPairByC(pairType, pairs.size());
        if(pairType.hasGenericType()) {
            C<?> valueType = pairType.generic(1);
            C<?> keyType = pairType.generic(0);
            for(Object o : pairs.entrySet()) {
                private_pairsPutOperation(o, result, keyType, valueType);
            }
            return result;
        }
        result.putAll(pairs);
        return result;
    }


    /* *******************************************************************************************
     *
     *          私有逻辑
     *
     * *******************************************************************************************
     * */

    @Note("根据 Map 集合实现类的全路径获取枚举映射的实例，如果获取不到则抛出异常")
    private static MapEnum private_getEnumIfNotExistsThrowException(String classname) {
        if("java.util.Map".equals(classname) || "java.util.AbstractMap".equalsIgnoreCase(classname)) {
            return HASH;
        }
        return getEnum(classname);
    }

    @Note("根据 Map 集合实现类的字节码获取枚举映射的实例，如果获取不到则抛出异常")
    private static MapEnum private_getEnumIfNotExistsThrowException(Class<?> implClass) {
        if(Map.class.equals(implClass) || AbstractMap.class.equals(implClass)) {
            return HASH;
        }
        return getEnum(implClass);
    }


    @Note("通过类型包装对象构建一个 java.util.Map 集合对象")
    private static Map private_buildMapByC(C<?> c, int size) {
        Class<?> mainType = c.getMainType();
        //HashMap
        if(Map.class.equals(mainType) || HashMap.class.equals(mainType)) {
            if(c.argCount() == 0) {
                return (size <= 0) ? new HashMap<>() : new HashMap<>(calcInitSize(size));
            }
            Object first = c.getArgValue(0);
            if(first instanceof Number) {
                int initSize = ((Number) first).intValue();
                Object second = c.getArgValue(1);
                if((second instanceof Float) || (second instanceof Double)) {
                    return new HashMap<>(calcInitSize(initSize), ((Number) second).floatValue());
                }
                return new HashMap<>(calcInitSize(initSize));
            }
            if(first instanceof Map) {
                return new HashMap<>((Map<?, ?>) first);
            }
            return (size <= 0) ? new HashMap<>() : new HashMap<>(calcInitSize(size));
        }
        //LinkedHashMap
        if(LinkedHashMap.class.equals(mainType)) {
            if(c.argCount() == 0) {
                return (size <= 0) ? new LinkedHashMap<>() : new LinkedHashMap<>(calcInitSize(size));
            }
            Object first = c.getArgValue(0);
            if(first instanceof Number) {
                int initSize = ((Number) first).intValue();
                Object second = c.getArgValue(1);
                if((second instanceof Float) || (second instanceof Double)) {
                    return new LinkedHashMap<>(calcInitSize(initSize), ((Number) second).floatValue());
                }
                return new LinkedHashMap<>(calcInitSize(initSize));
            }
            if(first instanceof Map) {
                return new LinkedHashMap<>((Map<?, ?>) first);
            }
            return (size <= 0) ? new LinkedHashMap<>() : new LinkedHashMap<>(calcInitSize(size));
        }
        //ConcurrentHashMap
        if(ConcurrentHashMap.class.equals(mainType)) {
            if(c.argCount() == 0) {
                return (size <= 0) ? new ConcurrentHashMap<>() : new ConcurrentHashMap<>(calcInitSize(size));
            }
            Object first = c.getArgValue(0);
            if(first instanceof Number) {
                int initSize = ((Number) first).intValue();
                Object second = c.getArgValue(1);
                if((second instanceof Float) || (second instanceof Double)) {
                    float load = ((Number) second).floatValue();
                    Object third = c.getArgValue(2);
                    if(third instanceof Number) {
                        int level = ((Number) third).intValue();
                        return new ConcurrentHashMap<>(calcInitSize(initSize), load, level);
                    }
                    return new ConcurrentHashMap<>(calcInitSize(initSize), load);
                }
                return new ConcurrentHashMap<>(calcInitSize(initSize));
            }
            if(first instanceof Map) {
                return new ConcurrentHashMap<>((Map<?, ?>) first);
            }
            return (size <= 0) ? new ConcurrentHashMap<>() : new ConcurrentHashMap<>(calcInitSize(size));
        }
        //TreeMap
        if(TreeMap.class.equals(mainType)) {
            if(c.argCount() == 0) return new TreeMap<>();
            Object first = c.getArgValue(0);
            if(first instanceof Comparator) return new TreeMap<>((Comparator) first);
            if(first instanceof Map) return new TreeMap<>((Map<?, ?>) first);
            return new TreeMap<>();
        }
        //ConcurrentSkipListMap
        if(ConcurrentSkipListMap.class.equals(mainType)) {
            if(c.argCount() == 0) return new ConcurrentSkipListMap<>();
            Object first = c.getArgValue(0);
            if(first instanceof Comparator) return new ConcurrentSkipListMap<>((Comparator) first);
            if(first instanceof Map) return new ConcurrentSkipListMap<>((Map<?, ?>) first);
            return new ConcurrentSkipListMap<>();
        }
        return (Map) ObjKit.buildObject(c);
    }


    @Note("当最终结果为 Map 集合时，处理 key 的类型为字符串的情况")
    private static Object private_handleKeyByMap(Object key, C<?> keyType, Class<?> containerType) {
        if(keyType == null) return key;
        if(String.class.equals(keyType.getMainType())) {
            if(ConcurrentHashMap.class.equals(containerType) || Hashtable.class.equals(containerType)) {
                return ObjKit.toStringValue(key, "null", false);
            }
            return ObjKit.toStringValue(key, null, false);
        }
        return ObjKit.toRealValue(key, keyType);
    }


    @Note("当最终结果为自定义键值对容器时，处理 key 的类型为字符串的情况")
    private static Object private_handleKeyByPair(Object key, C<?> keyType, MapEnum impl) {
        if(keyType == null) return key;
        if(String.class.equals(keyType.getMainType())) {
            return (impl == MapEnum.CONCURRENT)
                    ? ObjKit.toStringValue(key, "null", false)
                    : ObjKit.toStringValue(key, null, false);
        }
        return ObjKit.toRealValue(key, keyType);
    }


    @Note("通过类型包装对象构建一个自定义键值对集合对象")
    private static OwnPairs private_buildPairByC(C<?> c, int size) {
        Class<?> mainType = c.getMainType();
        if(JsonPair.class.equals(mainType)) {
            if(c.argCount() == 0) return new JsonPair();
            Object first = c.getArgValue(0);
            Object second = c.getArgValue(1);
            int code = -1;
            try {
                Integer i = BasicEnum.intValue(first);
                if(i != null) code = i;
            } catch (Exception ignored) {}
            String message = (second == null) ? "" : second.toString();
            return new JsonPair(code, message);
        }
        if(OwnPair.class.equals(mainType) && c.argCount() == 0) {
            return new OwnPair(size);
        }
        if(OwnMap.class.equals(mainType) && c.argCount() == 0) {
            return new OwnMap<>(size);
        }
        if(OwnPairs.class.equals(mainType) || AbsOwnPair.class.equals(mainType)) {
            if(c.argCount() == 0) return new OwnMap<>(calcInitSize(size));
            C<OwnMap> newC = new C<OwnMap>() {};
            c.copyTo(newC);
            return ObjKit.buildObject(newC);
        }
        return (OwnPairs) ObjKit.buildObject(c);
    }


    @Note("将自定义键值对容器重复的 put 操作抽取出来，避免代码冗余")
    private static void private_pairsPutOperation(Object o, OwnPairs result, C<?> keyType, C<?> valueType) {
        Map.Entry e = (Map.Entry) o;
        Object realValue = ObjKit.toRealValue(e.getValue(), valueType);
        Object realKey = private_handleKeyByPair(e.getKey(), keyType, result.getImplEnum());
        result.put(realKey, realValue);
    }
}
